
#ifndef _OPENGLFRAME_H_
#define _OPENGLFRAME_H_

#include "arcball.h"
#include "atmatrix.h"
#include "typedefs.h"
#include "texture.h"
#include "glSelection.h"

#include <QtOpenGL/QGLWidget>
#include <QtGui>

#include <vector>
#include <list>
#include <map>
#include <algorithm>
#include <sstream>

using namespace std;

/// A wrapper over QGLWidget.
class OpenGLFrame: public QGLWidget {
   
   Q_OBJECT
public:
   /// Constructor.
   OpenGLFrame(QWidget* parent=0, const QGLWidget* shareWidget = 0, Qt::WFlags f=0);
   ~OpenGLFrame();
   
   /// Sets the interaction mode
   void setInteractionMode(InteractionMode m) { interactionMode = m; }
   
   /// It sets the projection/modelview matrices
   //~ void setGLview(); 
   
   /// It sets the projection/modelview matrices
   /// @param c the center point
   /// @param diam the diameter
   void setGLview();
   
   void meshRenderMode(MeshRenderMode mrm)      { meshrendermode_mask = mrm; }
   void viewItemOn(ViewItems v)                 { viewitems_mask = viewitems_mask | v; } // inclusive-OR
   void viewItemOff(ViewItems v)                { viewitems_mask = viewitems_mask ^ v; } // exclusive-or
   void lightingOnOff(bool l)                   { is_lightingOn = l; }
   bool isProjectionOrtho()                     { return isProjOrtho; }
   void orthographic(bool o) { 
      (o)?(isProjOrtho=true):(isProjOrtho=false);
   }
   
   /// Returns the numer of frames
   virtual int nMaxofFrames() { return 0; }
   /// Returns the ID of the selected object
   int getSelectedId() { return idSelected; }
   
protected:
   
   /// OpenGL initialization.
   void initializeGL ();
   /// Drawing callback.
   
   /// Resize callback.
   /// @param width the width of the new window.
   /// @param height the height of the new window.
   void resizeGL (int width, int height);
   
   /// Returns the world coordinates of a point in screen space
   Point3 screenToWorld(int x, int y);
   
   /// Returns the translation vector in world coordinates of two points in screen space
   Vector3 screenToWorld(int xi, int yi, int xe, int ye);
   
   Vector3 getTranslationWorld(int x, int y, int xlast, int ylast);
   
   /// Mouse callback functions
   virtual void mousePressEvent(QMouseEvent *e);
   virtual void mouseMoveEvent(QMouseEvent *e);
   virtual void mouseReleaseEvent(QMouseEvent *e);
   virtual void wheelEvent(QWheelEvent *e);
   virtual void keyPressEvent(QKeyEvent *e);
   
   void genWorldLimits(Point3 c = Point3(0,0,0), Number radius = 1.0);
   void drawFloor();
   /// This function is from http://www.devmaster.net community.
   void createShadowProjectionMatrix(float *l, float *e, float *n);
   /// Renders the FPS 
   void fpsInfo();
   /// Draws the objects in selection mode
   void paintGLselection();
   
public slots:
   /// Zoom in operation.
   void zoomIn ();
   /// Zoom out operation.
   void zoomOut ();
   /// Zoom All operation.
   void zoomAll ();
   
protected:
   bool                    is_lightingOn;
   bool                    isProjOrtho;     // true when projection is perspective. false when perspective
   int                     meshrendermode_mask;
   unsigned                viewitems_mask;
   InteractionMode         interactionMode;  // Sets the interaction mode
   
   /// opengl data
   float                   fovy;         // Specifies the field of view angle, in degrees, in the y direction
   float                   zoomFactor;   // zoom factor
   float                   cameye[3];    // camera's eye
   float                   cameyeI[3];    // camera's eye
   float                   camcenter[3]; // Specifies the position of the reference point
   float                   mincoo[3];    // minimum point coordinates of the GL world
   float                   maxcoo[3];    // maximum point coordinates of the GL world
   GLdouble                mMtx[16], pMtx[16];  /// modelview/projection matrix
   GLint                   viewport[4];         /// the viewport
   float                   objDistance;
   float                   WorldWidth, WorldHeight;
   //~ float                   nearplane, farplane;
   
   /// the opengl world
   GLdouble nearplane, farplane; // planes on Z axis
   GLdouble leftplane, rightplane; // planes on X axis
   GLdouble bottomplane, topplane; // planes on Y axis
   
   /// time info
   float                   cfps;
   float                   lastTime;
   time_t                  start, end;
   unsigned                frame;
   
   float                   shadowMatrix[16]; // Shadow matrix
   Point3                  floor[4]; // four points of the plane
   Plane3                  pfloor;   // floor's plane
   ArcBall                 arcball; // An arcball object
   Point3                  cursor3D; // Position of 3D cursor
   Texture                 *texFloor; // floor texture
   Texture                 spriteTexCtlPoint;
   //~ GLSLKernel              kernel_xray;
   
   int                     currentFrame;
   
   AMatrix<GLfloat>        sceneT;
   AMatrix<GLfloat>        sceneIniT;
   Point3                  grabLast, grabStart;
   int                     xini, yini; // initial mouse position
   int                     xlast, ylast; // last mouse poisiton
   
   Selection                selection;  // the performer of selection operations
   int                      idSelected; // selected objetc identifier
public slots:
   void animateFrame(int);
   
private:
};

#endif
